const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

const UserSchema = new mongoose.Schema(
  {
    username: {
      type: String,
      required: false, // 改为非必填，因为可以使用微信昵称
      unique: true,
      sparse: true, // 允许多个null值的情况下保持唯一性
      trim: true,
      minlength: [3, '用户名至少需要3个字符']
    },
    email: {
      type: String,
      required: false, // 改为非必填，因为微信登录不一定有邮箱
      unique: true,
      sparse: true, // 允许多个null值的情况下保持唯一性
      match: [
        /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/,
        '请输入有效的邮箱地址'
      ],
      default: null // 确保默认为null
    },
    password: {
      type: String,
      required: false, // 改为非必填，微信登录不需要密码
      minlength: [6, '密码至少需要6个字符'],
      select: false
    },
    name: {
      type: String,
      required: false
    },
    phoneNumber: {
      type: String,
      required: false,
      trim: true
    },
    // 微信相关字段
    openid: {
      type: String,
      unique: true,
      sparse: true // 允许多个null值
    },
    unionid: {
      type: String,
      unique: true,
      sparse: true
    },
    nickname: String,
    avatarUrl: String,
    gender: {
      type: String,
      enum: ['男', '女', '其他', '未知', '保密'],
      default: '未知'
    },
    country: String,
    province: String,
    city: String,
    // 健康相关信息
    birthDate: {
      type: Date
    },
    age: {
      type: Number,
      min: 0,
      max: 120
    },
    height: {
      type: Number, // 单位：厘米
      min: 50,
      max: 250
    },
    weight: {
      type: Number, // 当前体重(kg)
      min: 20,
      max: 300
    },
    waistline: {
      type: Number, // 腰围(cm)
      min: 30,
      max: 200
    },
    bloodType: {
      type: String,
      enum: ['A型', 'B型', 'AB型', 'O型', 'A', 'B', 'AB', 'O'],
      default: null
    },
    targetWeight: {
      type: Number, // 目标体重(kg)
      min: 20,
      max: 300
    },
    bmi: {
      type: Number, // 体质指数
      min: 10,
      max: 50
    },
    // 新增字段 - 生理状况
    physiologicalStatus: {
      type: String,
      enum: ['normal', 'pregnant_early', 'pregnant_mid', 'pregnant_late', 'breastfeeding'],
      default: 'normal'
    },
    // 新增字段 - 体力活动水平
    activityLevel: {
      type: String,
      enum: ['light', 'moderate', 'heavy'],
      default: 'light'
    },
    diabetesType: {
      type: String,
      enum: ['1型', '2型', '妊娠期', '前期', '无', '其他'],
      default: '无'
    },
    diagnosisDate: {
      type: Date
    },
    bloodSugarTarget: {
      before: {
        min: { type: Number, default: 3.9 }, // 餐前最低值
        max: { type: Number, default: 7.2 }  // 餐前最高值
      },
      after: {
        min: { type: Number, default: 3.9 }, // 餐后最低值
        max: { type: Number, default: 10.0 } // 餐后最高值
      }
    },
    bloodPressureTarget: {
      systolic: {
        min: { type: Number, default: 90 },  // 收缩压最低值
        max: { type: Number, default: 120 }  // 收缩压最高值
      },
      diastolic: {
        min: { type: Number, default: 60 },  // 舒张压最低值
        max: { type: Number, default: 80 }   // 舒张压最高值
      }
    },
    // 营养摄入目标
    nutritionTarget: {
      calories: { type: Number, default: 2200 },    // 每日卡路里目标 (kcal)
      carbs: { type: Number, default: 275 },        // 每日碳水目标 (g)
      protein: { type: Number, default: 110 },      // 每日蛋白质目标 (g)
      fat: { type: Number, default: 73 }            // 每日脂肪目标 (g)
    },
    medicationInfo: [{
      name: String,
      dosage: String,
      frequency: String,
      startDate: Date,
      endDate: Date,
      notes: String,
      isActive: { type: Boolean, default: true }
    }],
    medicalHistory: {
      conditions: [String],
      allergies: [String],
      surgeries: [{
        name: String,
        date: Date,
        notes: String
      }],
      familyHistory: [String]
    },
    emergencyContact: {
      name: String,
      relationship: String,
      phoneNumber: String
    },
    lifestyle: {
      smokingStatus: { type: String, enum: ['从不', '已戒烟', '偶尔', '经常'], default: '从不' },
      alcoholConsumption: { type: String, enum: ['从不', '偶尔', '适量', '频繁'], default: '从不' },
      exerciseFrequency: { type: String, enum: ['从不', '偶尔', '每周数次', '每天'], default: '偶尔' }
    },
    isActive: {
      type: Boolean,
      default: true
    },
    role: {
      type: String,
      enum: ['user', 'admin'],
      default: 'user'
    },
    // 是否已完成初始设置（用于引导新用户完成健康信息填写）
    isProfileComplete: {
      type: Boolean, 
      default: false
    },
    notificationSettings: {
      enableReminders: { type: Boolean, default: true },
      medicationReminders: { type: Boolean, default: true },
      bloodSugarReminders: { type: Boolean, default: true },
      exerciseReminders: { type: Boolean, default: true },
      healthTips: { type: Boolean, default: true }
    },
    lastLoginAt: {
      type: Date,
      default: Date.now
    }
  },
  {
    timestamps: true
  }
);

// 保存前加密密码并计算营养目标
UserSchema.pre('save', async function (next) {
  // 只有设置了密码的情况下才进行加密
  if (this.password && this.isModified('password')) {
    const salt = await bcrypt.genSalt(10);
    this.password = await bcrypt.hash(this.password, salt);
  }
  
  // 计算BMI
  if (this.height && this.weight) {
    // BMI = 体重(kg) / (身高(m)^2)
    const heightInMeters = this.height / 100;
    this.bmi = this.weight / (heightInMeters * heightInMeters);
    this.bmi = parseFloat(this.bmi.toFixed(1)); // 保留一位小数
  }
  
  // 根据出生日期计算年龄
  if (this.birthDate && !this.age) {
    const today = new Date();
    const birthDate = new Date(this.birthDate);
    let age = today.getFullYear() - birthDate.getFullYear();
    const monthDiff = today.getMonth() - birthDate.getMonth();
    
    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
      age--;
    }
    
    this.age = age;
  }
  
  // 计算个性化营养目标
  if (this.gender && this.age && this.height && this.weight && this.activityLevel) {
    this.calculateNutritionTargets();
  }
  
  next();
});

// 计算个性化营养目标
UserSchema.methods.calculateNutritionTargets = function() {
  // 基础代谢率计算 (Harris-Benedict方程)
  let bmr = 0;
  
  if (this.gender === '男') {
    // 男性 BMR = 88.362 + (13.397 × 体重kg) + (4.799 × 身高cm) - (5.677 × 年龄)
    bmr = 88.362 + (13.397 * this.weight) + (4.799 * this.height) - (5.677 * this.age);
  } else if (this.gender === '女') {
    // 女性 BMR = 447.593 + (9.247 × 体重kg) + (3.098 × 身高cm) - (4.330 × 年龄)
    bmr = 447.593 + (9.247 * this.weight) + (3.098 * this.height) - (4.330 * this.age);
  } else {
    // 默认使用平均公式
    bmr = 88.362 + (13.397 * this.weight) + (4.799 * this.height) - (5.677 * this.age);
  }
  
  // 活动系数
  let activityFactor = 1.2; // 默认轻度活动
  
  switch(this.activityLevel) {
    case 'light':
      activityFactor = 1.375; // 轻度活动 (每周轻度运动1-3天)
      break;
    case 'moderate':
      activityFactor = 1.55; // 中度活动 (每周中度运动3-5天)
      break;
    case 'heavy':
      activityFactor = 1.725; // 重度活动 (每周剧烈运动6-7天)
      break;
  }
  
  // 总热量需求
  let caloriesTarget = Math.round(bmr * activityFactor);
  
  // 针对特殊生理状况调整
  if (this.gender === '女' && this.physiologicalStatus !== 'normal') {
    switch(this.physiologicalStatus) {
      case 'pregnant_early':
        caloriesTarget += 340; // 孕早期额外需要约340卡
        break;
      case 'pregnant_mid':
      case 'pregnant_late':
        caloriesTarget += 450; // 孕中晚期额外需要约450卡
        break;
      case 'breastfeeding':
        caloriesTarget += 500; // 哺乳期额外需要约500卡
        break;
    }
  }
  
  // 对于糖尿病患者，适当降低碳水比例，提高蛋白质比例
  let carbsPercentage = 0.5; // 默认碳水占50%
  let proteinPercentage = 0.2; // 默认蛋白质占20%
  let fatPercentage = 0.3; // 默认脂肪占30%
  
  if (this.diabetesType && this.diabetesType !== '无') {
    // 糖尿病患者适当降低碳水，增加蛋白质
    carbsPercentage = 0.45;
    proteinPercentage = 0.25;
    fatPercentage = 0.3;
  }
  
  // 计算各营养素目标
  this.nutritionTarget = {
    calories: caloriesTarget,
    carbs: Math.round((caloriesTarget * carbsPercentage) / 4), // 碳水 4卡/克
    protein: Math.round((caloriesTarget * proteinPercentage) / 4), // 蛋白质 4卡/克
    fat: Math.round((caloriesTarget * fatPercentage) / 9) // 脂肪 9卡/克
  };
};

// 比较密码
UserSchema.methods.matchPassword = async function (enteredPassword) {
  // 如果没有设置密码，直接返回false
  if (!this.password) {
    return false;
  }
  return await bcrypt.compare(enteredPassword, this.password);
};

// 更新最后登录时间
UserSchema.methods.updateLastLogin = function() {
  this.lastLoginAt = Date.now();
  return this.save();
};

module.exports = mongoose.model('User', UserSchema); 